package com.zhb.zhbojbackendgateway.filter;



import com.zhb.zhbojbackendcommon.common.ErrorCode;
import com.zhb.zhbojbackendcommon.exception.BusinessException;
import com.zhb.zhbojbackendcommon.utils.JwtUtils;
import com.zhb.zhbojbackendgateway.blackfilter.BlackIpUtils;
import com.zhb.zhbojbackendmodel.model.enums.UserRoleEnum;
import io.jsonwebtoken.Claims;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;

@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();
    // 不需要验证token的路径
    private static final String[] WHITE_LIST = {
            "/api/user/login",
            "/api/user/get/login",
            "/api/user/register",
            "/api/user/logout",
            "/api/doc.html",
            "/api/v3/api-docs",
            "/api/v2/api-docs",
            "/api/swagger-resources",
            "/api/swagger-ui.html",
            "/api/webjars/**",
            "/api/comment/v2/**",
            "/api/question/v2/**",
            "/api/judge/v2/**",
            "/api/user/v2/**",
    }; /**
     * 判断是否为白名单路径
     * @param path 请求路径
     * @return 是否在白名单中
     */
    private boolean isWhiteListPath(String path) {
        for (String whitePath : WHITE_LIST) {
            if (antPathMatcher.match(whitePath, path)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest serverHttpRequest = exchange.getRequest();
        String path = serverHttpRequest.getURI().getPath();
        //获取客户端IP地址
        String ipAddress = NetUtils.getIpAddress(serverHttpRequest);
        // 判断该 IP 是否在黑名单中
        if (BlackIpUtils.isBlackIp(ipAddress)) {
            // 如果是黑名单 IP，返回错误信息
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.FORBIDDEN);  // 设置 HTTP 状态为 Forbidden
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            DataBuffer dataBuffer = dataBufferFactory.wrap("黑名单IP，禁止访问".getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(dataBuffer));  // 返回自定义的错误信息
        }
        // 如果 IP 不在黑名单中，继续执行后续的过滤器
        // 判断路径中是否包含 inner，只允许内部调用
        if (antPathMatcher.match("/**/inner/**", path)) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.FORBIDDEN);
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            DataBuffer dataBuffer = dataBufferFactory.wrap("无权限".getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(dataBuffer));
        }

        // todo 统一权限校验，通过 JWT 获取登录用户信息
        //2. 公开接口（如登录注册）放行
        if (isWhiteListPath(path)) {
            return chain.filter(exchange);
        }
        //3.验证 jwt
        String token = serverHttpRequest.getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token) || !token.startsWith("Bearer ")) {
            return writeError(exchange.getResponse(), "未提供token");
        }
        try {
            //4. 解析jwt
            token=token.substring(7);
            Claims claims = JwtUtils.parseToken(token);
            Long userId = Long.parseLong(claims.get("userId", String.class));
            String userRole = claims.get("userRole", String.class);
            if(UserRoleEnum.BAN.getValue().equals(userRole)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"该账号已被封禁");
            }

            //将用户信息添加到请求头中，传递给下游服务
            ServerHttpRequest newRequest = serverHttpRequest.mutate()
                    .header("X-user-Id", userId.toString())
                    .header("X-user-Role", userRole)
                    .build();
            return chain.filter(exchange.mutate().request(newRequest).build());
        } catch (Exception e) {
            return writeError(exchange.getResponse(),"Token无效或已过期");
        }
    }

    /**
     * 优先级提到最高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
    //设置响应状态码为 401（未授权）
    //将错误信息写入响应体
    //返回 Mono 完成响应
    private Mono<Void> writeError(ServerHttpResponse response, String message) {
        return writeError(response,message,HttpStatus.UNAUTHORIZED);
    }
    private Mono<Void> writeError(ServerHttpResponse response, String message,HttpStatus httpStatus) {
        response.setStatusCode(httpStatus);
        DataBuffer buffer = response.bufferFactory().wrap(message.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
    }
}
